﻿namespace ClearSpringNet.Stream.Cardinality
{
    public static class Integer
    {
        public static int Size = 32;

        // De Bruijn 
        static readonly int[] Positions =
            {
                0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
                31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
            };

        public static int NumberOfTrailingZeros(int number)
        {
            uint res = unchecked((uint)(number & -number) * 0x077CB531U) >> 27;
            return res == 0 ? Size : Positions[res];
        }

        public static int NumberOfLeadingZeros(int n)
        {
            var b = new char[Size];
            int pos = 31;
            int i = 0;

            while (i < Size)
            {
                if ((n & (1 << i)) != 0)
                {
                    b[pos] = '1';
                }
                else
                {
                    b[pos] = '0';
                }
                pos--;
                i++;
            }

            var x = new string(b).TrimStart('0');
            return n == 0 ? Size : Size - x.Length;
        }

        public static string ToBinaryString(int number)
        {
            var b = new char[32];
            var pos = 31;
            var i = 0;

            while (i < 32)
            {
                if ((number & (1 << i)) != 0)
                {
                    b[pos] = '1';
                }
                else
                {
                    b[pos] = '0';
                }
                pos--;
                i++;
            }
            return new string(b);
        }

        public static int BitCount(int number)
        {
            var pos = 31;
            var i = 0;
            var bitCount = 0;

            while (i < 32)
            {
                if ((number & (1 << i)) != 0)
                {
                    bitCount++;
                }
                pos--;
                i++;
            }
            return bitCount;
        }

    }
}